package com.lingkang.dbtodoc.service.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.lingkang.dbtodoc.constants.DataBaseType;
import com.lingkang.dbtodoc.utils.DbSqlUtils;
import com.lingkang.dbtodoc.entity.ColumnInfo;
import com.lingkang.dbtodoc.entity.DataBaseSchema;
import com.lingkang.dbtodoc.entity.TableSchema;
import com.lingkang.dbtodoc.pojo.DbConnect;
import com.lingkang.dbtodoc.service.DBService;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Service;

/**
 * @author 绫小路
 * @date 2021/2/1 1:06
 * @description
 */
@Slf4j
@Service
public class DBServiceImpl implements DBService {

  @Autowired
  private ApplicationContext applicationContext;
  @Autowired
  private JdbcTemplate jdbcTemplate;
  @Autowired
  private DataBaseType dataBaseType;

  @Override
  public String updateConnect(DbConnect connect, HttpServletRequest request) {
    String beanName = "dataSource";
    DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
    if (defaultListableBeanFactory.containsBeanDefinition(beanName)) {//存在删除
      defaultListableBeanFactory.removeBeanDefinition(beanName);
    }
    try {
      BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DriverManagerDataSource.class);
      //注册bean.
      defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
    } catch (Exception e) {
      log.error("栈信息", e);
      return ExceptionUtil.stacktraceToString(e);
    }
    //刷新链接信息
    DriverManagerDataSource dataSource = (DriverManagerDataSource) applicationContext.getBean(beanName);
    dataSource.setDriverClassName(connect.getDriverClassName());
    dataSource.setUrl(connect.getUrl());
    dataSource.setUsername(connect.getUsername());
    dataSource.setPassword(connect.getPassword());

    String type = "mysql";
    if (connect.getDriverClassName().toLowerCase().indexOf("mysql") != -1) {
      type = "mysql";
    }
    //刷新bean dataBaseType
    dataBaseType.setType(type);

    try {
      //刷新 jdbcTemplate
      jdbcTemplate.setDataSource(dataSource);
    } catch (Exception e) {
      log.error("刷新Bean jdbcTemplate 失败", e);
    }

    try {
      Map<String, Object> mysql = jdbcTemplate.queryForMap(DbSqlUtils.init(dataBaseType.getType()));
      log.info("-------------初始化数据源成功！{}------------------", mysql);
    } catch (DataAccessException e) {
      log.error("初始化数据源失败！", e);
      return ExceptionUtil.stacktraceToString(e);
    }
    request.getSession().setAttribute("dbinfo",
        type + " " + jdbcTemplate.queryForMap(DbSqlUtils.getVersion(dataBaseType.getType())).get("version"));
    return null;
  }

  @Override
  public List<DataBaseSchema> getDataBaseSchema() {
    List<DataBaseSchema> dataBaseSchemas = jdbcTemplate.query(DbSqlUtils.get(dataBaseType.getType()),
        new BeanPropertyRowMapper<>(DataBaseSchema.class));
    return dataBaseSchemas;
  }

  @Override
  public void updateTableComment(String table, String comment) {
    try {
      jdbcTemplate.execute(DbSqlUtils.updateTableComment(dataBaseType.getType(), table, comment));
    } catch (DataAccessException e) {
      e.printStackTrace();
      throw new RuntimeException("更新失败，请检是否存在更新权限\n" + e.getMessage());
    }
  }

  @Override
  public List<TableSchema> getTableSchema() {
    List<DataBaseSchema> dataBaseSchema = this.getDataBaseSchema();
    List<TableSchema> schemas = new ArrayList<>();
    for (DataBaseSchema baseSchema : dataBaseSchema) {
      List<ColumnInfo> query = jdbcTemplate.query(DbSqlUtils.getColumn(dataBaseType.getType(), baseSchema.getTableName()),
          new BeanPropertyRowMapper<>(ColumnInfo.class));
      TableSchema schema = new TableSchema();
      schema.setTableName(baseSchema.getTableName());
      schema.setDataBaseName(baseSchema.getDataBaseName());
      schema.setColumnInfo(query);
      schemas.add(schema);
    }
    return schemas;
  }

  @Override
  public TableSchema getTableSchema(String tableName) {
    List<ColumnInfo> query = jdbcTemplate.query(DbSqlUtils.getColumn(dataBaseType.getType(), tableName),
        new BeanPropertyRowMapper<>(ColumnInfo.class));
    if (query.isEmpty()) {
      return null;
    }
    TableSchema schema = new TableSchema();
    schema.setTableName(tableName);
    schema.setColumnInfo(query);
    schema.setDataBaseName((String) jdbcTemplate.queryForMap(DbSqlUtils.getDataBaseName(dataBaseType.getType())).get("dataBaseName"));
    return schema;
  }

  @Override
  public void updateColumnComment(String tableName, String columnName, String comment) {
    try {
      jdbcTemplate.update(DbSqlUtils.updateColumnComment(dataBaseType.getType(), tableName, columnName, comment));
    } catch (DataAccessException e) {
      e.printStackTrace();
      throw new RuntimeException("更新失败，请检是否存在更新权限\n" + e.getMessage());
    }
  }
}
